/*
 * -------------------------------------------------------------------------
 * webview管理器
 * -------------------------------------------------------------------------
 */

/*app对象实例*/
let app;
const _           = require('lodash');
const fs          = require('fs');
const path        = require('path');
const semver      = require('semver');
const electron    = require('electron');
const is          = require('../helper/is');
const downloader  = require('../helper/downloader');
const IPC_WEBVIEW = require('../src/ipc/dict').IPC_WEBVIEW;
const packageJson = require('../package.json');
const file        = require('../helper/file/log');
const ipcMain     = electron.ipcMain;

/**
 * 初始化
 * @param appInstance
 */
function initialize (appInstance) {
    /*复写app实例*/
    app = appInstance;
    
    /*渲染进程获取webview配置*/
    ipcMain.on(IPC_WEBVIEW.GET_SETTING, (e, name) => checkAndGetSetting(name));
    
    /*渲染进程请求安装配置文件*/
    ipcMain.on(IPC_WEBVIEW.CONFIRM_INSTALL, (e, { name }) => confirmInstall({ name }));
}

/**
 * 格式化名称
 * @param name
 * @return {string|*}
 */
function formatName (name) {
    return name.startsWith('kit_') ? name.substr(4) : name;
}

/**
 * 获取本地配置
 * @param name
 * @return {{}}
 */
function getSetting (name) {
    /*结果*/
    let json = {};
    
    /*格式化名称*/
    name = formatName(name);
    
    /*文件*/
    let file = path.resolve(path.dirname(app.getPath('exe')), 'webviews', `${name}.json`);
    
    /*文件不存在*/
    if (!fs.existsSync(file)) return json;
    
    /*获取文件内容*/
    try {
        let content = fs.readFileSync(file).toString();
        json        = JSON.parse(content);
    }
    catch (e) { }
    
    /*返回配置*/
    return json;
}

/**
 * 检查更新并获取配置
 * @param name
 * @return {Promise<number>}
 */
async function checkAndGetSetting (name) {
    /*格式化name*/
    let fmtName = formatName(name);
    
    /*当前设置*/
    let curSetting = getSetting(fmtName);
    
    /*获取订阅信息*/
    let feed = await downloader.getUrl(packageJson.configs.feed.webviews).catch(() => {});
    if (is.empty(feed)) return Promise.reject();
    
    /*搜索更新*/
    let newUpdate = searchUpdate(fmtName, curSetting, feed.data);
    
    /*当前状态*/
    let status;
    if (is.empty(curSetting)) {
        status = IPC_WEBVIEW.STATUS.NO_INSTALL;
    }
    else if (!is.empty(newUpdate)) {
        status = IPC_WEBVIEW.STATUS.NEW_VERSION;
    }
    else {
        status = IPC_WEBVIEW.STATUS.INSTALLED;
    }
    
    /*通知渲染进程*/
    app.$windowMain.webContents.send(IPC_WEBVIEW.PUT_SETTING, { name, status, setting: curSetting, update: newUpdate });
}

/**
 * 搜索新版本
 * @param name
 * @param curSetting
 * @param feed
 * @return {{}|unknown}
 */
function searchUpdate (name, curSetting, feed) {
    try {
        /*当前版本号*/
        let curVersion = is.empty(curSetting) ? '0.0.0' : curSetting.version;
        
        /*解析feed*/
        let feeds = JSON.parse(feed);
        
        /*查找升级信息*/
        let update = _.find(feeds, v => {
            const matchName    = v.name.toUpperCase() === name.toUpperCase();
            const matchVersion = semver.gt(v.version, curVersion);
            return matchName && matchVersion;
        });
        
        /*无升级信息*/
        if (!update) return {};
        
        /*新版本通知*/
        return update;
    }
    catch (e) { }
    
    return {};
}

/**
 * 确认安装
 * @param name
 * @return {Promise<void>}
 */
async function confirmInstall ({ name }) {
    /*格式化name*/
    let fmtName = formatName(name);
    
    /*获取订阅信息*/
    let feed = await downloader.getUrl(packageJson.configs.feed.webviews).catch(ret => putInstallStatus(name, 1, ret.data));
    if (is.empty(feed)) return Promise.reject();
    
    /*搜索更新*/
    let newUpdate = searchUpdate(fmtName, null, feed.data);
    if (is.empty(newUpdate)) {
        putInstallStatus(name, 1, '暂未发现更新');
        return Promise.reject();
    }
    
    /*下载目录*/
    let saveDir = path.resolve(path.dirname(app.getPath('exe')), 'webviews');
    
    /*创建目录*/
    file.mkdir(saveDir);
    
    /*保存路径*/
    let savePath = path.resolve(saveDir, `${fmtName}.json`);
    
    /*下载配置*/
    let update = await downloader.saveUrl(newUpdate.url, savePath).catch(ret => putInstallStatus(name, 1, ret.data));
    if (is.empty(update)) return Promise.reject();
    
    putInstallStatus(name, 0, '安装成功');
}

/**
 * 将安装状态通知到渲染进程
 * @param name
 * @param errCode
 * @param errMsg
 */
function putInstallStatus (name, errCode, errMsg) {
    app.$windowMain.webContents.send(IPC_WEBVIEW.INSTALL_RESULT, { name, errCode, errMsg });
}

/**
 * 导出
 * @type {{initialize: initialize}}
 */
module.exports = {
    initialize
};
